#include <stdio.h>
#include <stdlib.h>

#define N 10 // 缓冲区的初始大小

char *mystrchr(const char *str, int c);
char *mystrstr(const char *haystack, const char *needle);
int mygetline(char **lineptr, int *n);

int main(void)
{
    const char str1[] = "Hello World!";
    const char str2[] = "orl";
    char ch = 'o';
    char *ptr = NULL;
    char *ret;
    char *line = NULL;
    int size = 0; // 实际缓冲区大小

    ptr = mystrchr(str1, ch);

    if (ptr != NULL) {
        printf("字符 'o' 出现的位置为 %ld。\n", ptr - str1 + 1);
        printf("|%c| 之后的字符串是 - |%s|\n", ch, ptr);
    } else {
        printf("没有找到字符 'o' 。\n");
    }

    ret = mystrstr(str1, str2);
    printf("子字符串是： %s\n", ret);


    while (mygetline(&line, &size) != -1) { // 会循环读取，可以手动结束程序 
        printf("size:%d\n", size);
        printf("line:%s", line);
    }

    return 0;
}


/* 用于查找字符串中的一个字符，并返回该字符在字符串中第一次出现的位置。
 *
 * 返回值：如果在字符串 str 中找到字符 c，则函数返回指向该字符的指针，如果未找到该字符则返回 NULL。
 */
char *mystrchr(const char *str, int c)
{
    while (*str) {
        if (*str == c) {
            return (char *)str; // 需要强转，否则警告不能返回指向常量的指针
        }
        str++;
    }

    return NULL;
}

/* 在字符串 haystack 中查找第一次出现字符串 needle 的位置，不包含终止符 '\0'。
 *
 * 返回值：指向 haystack 中第一次出现 needle 的位置的指针。如果 needle 未在 haystack 中找到，则返回 NULL。
 */
char *mystrstr(const char *haystack, const char *needle)
{
    int i, j;
    for (i = 0; haystack[i]; i++) {
        for (j = 0; needle[j]; j++) {
            if (!(haystack[i + j] && haystack[i + j] == needle[j]))
                break;
        }
        if (!needle[j]) 
            return (char *)(haystack + i);
    }

    return NULL;
}

/* 从控制台中读取一整行，将包含文本的缓冲区的地址存储到 *lineptr 中。 缓冲区以 '\0' 结尾，包括换行符（如果找到）。
 *
 * 返回值：成功则返回读取的字节数。失败则返回-1。
 */
int mygetline(char **lineptr, int *n)
{
    char *tmp = NULL;
    char c;
    int len = 0;
    if (*lineptr == NULL || *n == 0) {
        tmp = malloc(sizeof(char) * N);
        if (tmp == NULL)
            return -1;

        *lineptr = tmp;
        *n = N;
    }

    do {
        scanf("%c", &c);
        (*lineptr)[len++] = c;

        if (len == *n - 1) { // 缓冲区满了，需要扩容
            tmp = realloc(*lineptr, 2 * (*n) * sizeof(char)); // 扩容二倍
            if (tmp == NULL) {
                free(*lineptr);
                *lineptr = NULL;
                *n = 0;
                return -1;
            }
            *lineptr = tmp;
            *n = 2 * (*n);
        }
    } while (c != '\n');

    (*lineptr)[len] = '\0'; // 以 '\0' 终止缓冲区
    return len;
}


